<?php

/*
    $dataOrg = "123456";
    $AESKey = "rN6LfP9qbILPabc938IixdFds3s5ksIqjcPyYxOPx4v";
    $iv = "";

    // 初始化
    $myAES_Encrypt = new AES_Encrypt();

    // 加密字符串
    $dataEncrypted = $myAES_Encrypt->encrypt($dataOrg, $AESKey, $iv);

    // 解密字符串
    $dataDecrypted = $myAES_Encrypt->decrypt($dataEncrypted, $AESKey, $iv);

    // 比较
    var_dump($dataOrg == $dataDecrypted);
 */
class AES_Encrypt{
    const BLOCK_SIZE = 32;

    private $RIJNDAEL;
    private $MODE;
    private $methodArr;

    public function __construct($method = null){
        if($method == null){
            $method = "AES-128-CBC";
        }
        $this->RIJNDAEL = null;
        $this->MODE = null;
        $this->methodArr = explode("-", $method);
        switch($this->methodArr[1]){
            case "128":
                $this->RIJNDAEL = MCRYPT_RIJNDAEL_128;
                break;
            case "192":
                $this->RIJNDAEL = MCRYPT_RIJNDAEL_192;
                break;
            case "256":
                $this->RIJNDAEL = MCRYPT_RIJNDAEL_256;
                break;
        }
        switch($this->methodArr[2]){
            case "CBC":
                $this->MODE = MCRYPT_MODE_CBC;
                break;
            case "CFB":
                $this->MODE = MCRYPT_MODE_CFB;
                break;
            case "ECB":
                $this->MODE = MCRYPT_MODE_ECB;
                break;
            case "NOFB":
                $this->MODE = MCRYPT_MODE_NOFB;
                break;
            case "OFB":
                $this->MODE = MCRYPT_MODE_OFB;
                break;
            case "STREAM":
                $this->MODE = MCRYPT_MODE_STREAM;
                break;
        }
        if($this->RIJNDAEL == null || $this->MODE == null){

            throw new Exception("invalid RIJNDAEL or MODE about '". $method. "'", 2000100);
        }
    }

    public function pkcs7Pad($str){
        $len = mb_strlen($str, '8bit');
        $c = 16 - ($len % 16);
        $str .= str_repeat(chr($c), $c);

        return $str;
    }

    private function pkcs7Encode($text){
        $text_length = strlen($text);

        $amount_to_pad = AES_Encrypt::BLOCK_SIZE - ($text_length % AES_Encrypt::BLOCK_SIZE);
        if ($amount_to_pad == 0) {
            $amount_to_pad = AES_Encrypt::BLOCK_SIZE;
        }

        $pad_chr = chr($amount_to_pad);
        $tmp = "";
        for ($index = 0; $index < $amount_to_pad; $index++) {
            $tmp .= $pad_chr;
        }

        return $text . $tmp;
    }

    private function pkcs7Decode($text){
        $pad = ord(substr($text, -1));
        if ($pad < 1 || $pad > 32) {
            $pad = 0;
        }

        return substr($text, 0, (strlen($text) - $pad));
    }

    public function encrypt($data, $key, $iv){
        $data = $this->pkcs7Encode($data);
        $encrypted = mcrypt_encrypt($this->RIJNDAEL, $key, $data, $this->MODE, $iv);
        $based_encrypted = base64_encode($encrypted);

        return $based_encrypted;
    }

    //aes/cbc/pkcs
    public function decrypt($data, $key, $iv){
        if(StringTool::startsWith(PHP_VERSION,"5"))
        {
            //$data = base64_decode($data);
            $encrypted = mcrypt_decrypt($this->RIJNDAEL, $key, $data, $this->MODE, $iv);
            $encrypted = $this->pkcs7Decode($encrypted);
    
            return $encrypted;
        }

        if(StringTool::startsWith(PHP_VERSION,"7"))
        {
            return openssl_decrypt(base64_encode($data), "aes-128-cbc", $this->key, 0, $this->key);
        }
    }
}
?>